﻿// ---------------------------------------------------------------------------------------------------------------------
//   Copyright (c) SRT Solutions 2009. All rights reserved.
// ---------------------------------------------------------------------------------------------------------------------

namespace SRTSolutions.Elevate.Guide
{
    using System;
    using System.Net;

    using NUnit.Framework;

    using SRTSolutions.Elevate;

    public class NullableTryParse
    {
        [Test]
        public void ParsingValues()
        {
            //when we have a string that we want to parse
            var dateTimeString = "Fri, 15 May 2009 20:10:57 GMT";

            //normally, we'd have to try to parse it like this
            DateTime value1;
            bool result = DateTime.TryParse(dateTimeString, out value1);
            Assert.IsTrue(result);

            //instead, we can use this syntax
            DateTime? value2 = dateTimeString.TryParseDateTime();


            Assert.IsTrue(value2.HasValue);
            Assert.AreEqual(value1, value2.Value);

            //NOTE: We provide these TryParse extensions for many
            //      other common types. See the unit tests below
            //      for details.
        }

        #region Unit Tests

        // These are a lot of the sample strings that are 
        // used in the .NET BCL examples:
        private static string[] stringsToParse = new string[]
            {
                "true",
                "false",
                "A",
                "1",
                "-2",
                "0x86",
                "-15",
                "abc",
                "-1.643e6",
                "-168934617882109132",
                "05/01/2009 14:57:32.8", 
                "2009-05-01 14:57:32.8", 
                "2009-05-01T14:57:32.8375298-04:00", 
                "5/01/2008 14:57:32.80 -07:00", 
                "1 May 2008 2:57:32.8 PM", 
                "16-05-2009 1:00:32 PM", 
                "Fri, 15 May 2009 20:10:57 GMT",
                "05/012008",
                "11:36 PM",
                "05/01/2008 +7:00",
                "Thu May 01, 2008",
                "5/1/2008 10:00 AM -07:00",
                "0",
                "14",
                "1:2:3",
                "0:0:0.250",
                "10.20:30:40.50",
                "99.23:59:59.9999999",
                "0023:0059:0059.0099",
                "24:0:0",
                "0:60:0",
                "0:0:60",
                "10:",
                ":10",
                "10:20:",
                ".123",
                "10.",
                "10.12",
                "127.0.0.1",
                "0:0:0:0:0:0:0:1",
                "some random text",
                ""
            };

        [Test]
        public void ParseAsBoolean()
        {
            foreach (string s in stringsToParse)
            {
                bool? result = s.TryParseBool();
                // Find expected values:
                bool expectedResult;
                bool success = bool.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullBoolean()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseBool(null));
        }

        [Test]
        public void ParseAsByte()
        {
            foreach (string s in stringsToParse)
            {
                byte? result = s.TryParseByte();
                // Find expected values:
                byte expectedResult;
                bool success = byte.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullByte()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseByte(null));
        }

        [Test]
        public void ParseAsChar()
        {
            foreach (string s in stringsToParse)
            {
                char? result = s.TryParseChar();
                // Find expected values:
                char expectedResult;
                bool success = char.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullChar()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseChar(null));
        }

        [Test]
        public void ParseAsDateTime()
        {
            foreach (string s in stringsToParse)
            {
                DateTime? result = s.TryParseDateTime();
                // Find expected values:
                DateTime expectedResult;
                bool success = DateTime.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullDateTime()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseDateTime(null));
        }

        [Test]
        public void ParseAsDateTimeOffset()
        {
            foreach (string s in stringsToParse)
            {
                DateTimeOffset? result = s.TryParseDateTimeOffset();
                // Find expected values:
                DateTimeOffset expectedResult;
                bool success = DateTimeOffset.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullDateTimeOffset()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseDateTimeOffset(null));
        }

        [Test]
        public void ParseAsDecimal()
        {
            foreach (string s in stringsToParse)
            {
                decimal? result = s.TryParseDecimal();
                // Find expected values:
                decimal expectedResult;
                bool success = decimal.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullDecimal()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseDecimal(null));
        }

        [Test]
        public void ParseAsDouble()
        {
            foreach (string s in stringsToParse)
            {
                double? result = s.TryParseDouble();
                // Find expected values:
                double expectedResult;
                bool success = double.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullDouble()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseDouble(null));
        }

        [Test]
        public void ParseAsShort()
        {
            foreach (string s in stringsToParse)
            {
                short? result = s.TryParseShort();
                // Find expected values:
                short expectedResult;
                bool success = short.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullShort()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseShort(null));
        }

        [Test]
        public void ParseAsInt()
        {
            foreach (string s in stringsToParse)
            {
                int? result = s.TryParseInt();
                // Find expected values:
                int expectedResult;
                bool success = int.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullInt()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseInt(null));
        }

        [Test]
        public void ParseAsLong()
        {
            foreach (string s in stringsToParse)
            {
                long? result = s.TryParseLong();
                // Find expected values:
                long expectedResult;
                bool success = long.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullLong()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseLong(null));
        }

        [Test]
        public void ParseAsFloat()
        {
            foreach (string s in stringsToParse)
            {
                float? result = s.TryParseFloat();
                // Find expected values:
                float expectedResult;
                bool success = float.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullFloat()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseFloat(null));
        }

        [Test]
        public void ParseAsUnsignedShort()
        {
            foreach (string s in stringsToParse)
            {
                ushort? result = s.TryParseUnsignedShort();
                // Find expected values:
                ushort expectedResult;
                bool success = ushort.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullUnsignedShort()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseUnsignedShort(null));
        }

        [Test]
        public void ParseAsUnsignedLong()
        {
            foreach (string s in stringsToParse)
            {
                ulong? result = s.TryParseUnsignedShort();
                // Find expected values:
                ulong expectedResult;
                bool success = ulong.TryParse(s, out expectedResult);
                Assert.AreEqual(success, result.HasValue);
                if (success)
                    Assert.AreEqual(expectedResult, result.Value);
            }
        }

        [Test]
        public void ParseNullUnsignedLong()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseUnsignedLong(null));
        }

        [Test]
        public void ParseAsIpAddress()
        {
            foreach (string s in stringsToParse)
            {
                IPAddress result = s.TryParseIPAddress();
                // Find expected values:
                IPAddress expectedResult;
                bool success = IPAddress.TryParse(s, out expectedResult);
                Assert.AreEqual(success, (result != null));
                if (success)
                    Assert.AreEqual(expectedResult, result);
            }
        }

        [Test]
        public void ParseNullIPAddress()
        {
            Assert.Throws<ArgumentNullException>(() => TryParseExtension.TryParseIPAddress(null));
        }

        #endregion
    }
}
